package handler

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
	"time"
	"yunpan/cache/log"
	"yunpan/common"
	"yunpan/config"
	dblayer "yunpan/db"
	"yunpan/meta"
	"yunpan/mq"
	"yunpan/store/oss"
	"yunpan/util"
)

/**
	上传接口
 */
func UploadHandler(w http.ResponseWriter, r *http.Request){
	if r.Method == http.MethodGet {
		data, err := ioutil.ReadFile("./static/view/index.html")
		if err != nil {
			fmt.Println("internel server")
			return
		}
		io.WriteString(w, string(data))
	} else if r.Method == http.MethodPost {
		file, head, err := r.FormFile("file")
		if err != nil {
			fmt.Println("Failed get form data:%s\n", err.Error())
			return
		}
		defer file.Close()

		fileMeta := meta.FileMeta{
			FileName: head.Filename,
			Location: "/Users/joe/work/yunpan/tmp/"+head.Filename,
			UploadAt: time.Now().Format("2006-01-02 15:04:05"),
		}

		newFile, err := os.Create(fileMeta.Location)
		if err != nil {
			fmt.Println("Failed create file:%s\n", err.Error())
			return
		}
		defer newFile.Close()

		fileMeta.FileSize, err = io.Copy(newFile, file)
		if err != nil {
			fmt.Println("Failed copy file:%s\n", err.Error())
		}

		newFile.Seek(0, 0)
		fileMeta.FileSha1 = util.FileSha1(newFile)

		newFile.Seek(0, 0)
		ossPath := "oss/"+fileMeta.FileSha1
		//option := []alioss.Option{
		//	alioss.ContentDisposition("attachment;filename=\""+fileMeta.FileName+"")}
		//err = oss.Bucket().PutObject(ossPath, newFile, option...)
		//if err != nil {
		//	log.Ob().Warn("upload failed"+err.Error())
		//	w.Write([]byte("Upload Failed!!!"))
		//	return
		//}
		fmt.Println("filename:"+fileMeta.FileName)

		data := mq.TransferData{
			FileHash: fileMeta.FileSha1,
			FileName: fileMeta.FileName,
			CurLocation: fileMeta.Location,
			DestLocation: ossPath,
			DestStoreType: common.StoreOSS,
		}

		pubData, _ := json.Marshal(data)
		suc := mq.Publish(
			config.TransExchangeName,
			config.TransOSSRoutingKey,
			pubData)


		if !suc {
			log.Ob().Warn("发送失败")
		}

		fileMeta.Location = ossPath
		_ = meta.UpdateFileMetaDB(fileMeta)

		r.ParseForm()
		username := r.Form.Get("username")

		res := dblayer.OnUserFileUploadFinished(username, fileMeta.FileSha1,fileMeta.FileName, fileMeta.FileSize)

		if res {
			http.Redirect(w, r, "/static/view/home.html", http.StatusFound)
		}

		w.Write([]byte("upload error"))

	}
}

func UploadSuccess(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w,"upload success")
}


func GetFileMetaHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	//filehash := r.Form["filehash"][0]
	filehash := r.Form.Get("filehash")
	//fMeta := meta.GetFileMeta(filehash)
	fMeta, err := meta.GetFileMetaDB(filehash)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	data, err := json.Marshal(fMeta)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.Write(data)
}

func FileQueryHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()

	limitCnt, _ := strconv.Atoi(r.Form.Get("limit"))
	username := r.Form.Get("username")
	//fileMetas := meta.GetLastFileMetas(limitCnt)

	userFiles, err := dblayer.QueryUserFileMetas(username, limitCnt)
	if err != nil {
		w.WriteHeader(http.StatusForbidden)
		return
	}

	data, err := json.Marshal(userFiles)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.Write(data)
}

func DownLoadHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	filesha1 := r.Form.Get("filehash")
	fm := meta.GetFileMeta(filesha1)
	f, err := os.Open(fm.Location)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	defer f.Close()
	data, err := ioutil.ReadAll(f)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/octect-stream")
	w.Header().Set("Content-Disposition","attachment;filename=\""+fm.FileName+"\"")
	w.Write(data)
}

func FileMetaUpdateHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	opType := r.Form.Get("op")
	filesha1 := r.Form.Get("filehash")
	newFileName := r.Form.Get("filename")

	if opType != "0" {
		w.WriteHeader(http.StatusForbidden)
		return
	}

	if r.Method != "POST" {
		w.WriteHeader(http.StatusForbidden)
		return
	}

	fm := meta.GetFileMeta(filesha1)
	fm.FileName = newFileName
	meta.UpdateFileMeta(fm)

	data, err := json.Marshal(fm)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusOK)
	w.Write(data)
}

func FileDeleteHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	filesha1 := r.Form.Get("filehash")
	fMeta := meta.GetFileMeta(filesha1)
	os.Remove(fMeta.Location)
	meta.RemoveFileMeta(filesha1)
	w.WriteHeader(http.StatusOK)
}

func TryFastUploadHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()

	username := r.Form.Get("username")
	filehash := r.Form.Get("filehash")
	filename := r.Form.Get("filename")
	filesize, _ := strconv.Atoi(r.Form.Get("filesize"))

	fileMeta, err := meta.GetFileMetaDB(filehash)
	if err != nil {
		log.Ob().Warn(err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	//秒传失败
	if fileMeta.FileSha1 == "" {
		resp := util.RespMsg{
			Code: -1,
			Msg:  "秒传失败",
		}
		w.Write(resp.JSONBytes())
		return
	}

	res := dblayer.OnUserFileUploadFinished(username, filehash, filename, int64(filesize))
	if res {
		resp := util.RespMsg{
			Code: 0,
			Msg:  "秒传成功",
		}
		w.Write(resp.JSONBytes())
		return
	} else {
		resp := util.RespMsg{
			Code: -2,
			Msg:  "秒传失败，请稍后再试",
		}
		w.Write(resp.JSONBytes())
		return
	}

}


func DownloadURLHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	filehash := r.Form.Get("filehash")

	row, _ := dblayer.GetFileMeta(filehash)
	signURL := oss.DownloadURL(row.FileAddr.String)
	w.Write([]byte(signURL))
}


func GETDownloadURLHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	filehash := r.Form.Get("filehash")

	row, _ := dblayer.GetFileMeta(filehash)
	url := "http://"+config.OSSBucket+"."+config.OSSEndpoint+"/"+row.FileAddr.String
	w.Write([]byte(url))
}